# -*- coding: utf-8 -*-
# @Time : 2023/7/30 2:00
# @Author : zxp
from rest_framework import serializers

from article.models import Article, Category, Tag, Avatar
from comment.serializers import CommentSerializer
from user_info.serializers import UserDetailSerializer


class AvatarSerializer(serializers.ModelSerializer):
    """文章标题图序列化器"""
    # 超链接url - ----此处为，文章标题图的url
    url = serializers.HyperlinkedIdentityField(view_name='avatar-detail')

    class Meta:
        model = Avatar
        fields = '__all__'


class TagSerializer(serializers.HyperlinkedModelSerializer):
    """标签序列化器"""

    # 判断标签是否有重复，重复就报错
    def check_tag_obj_exists(self, validated_data):
        text = validated_data.get('text')
        if Tag.objects.filter(text=text).exists():
            raise serializers.ValidationError('Tag with text {} exists.'.format(text))

    def create(self, validated_data):
        self.check_tag_obj_exists(validated_data)
        return super().create(validated_data)

    def update(self, instance, validated_data):
        self.check_tag_obj_exists(validated_data)
        return super().update(instance, validated_data)

    class Meta:
        model = Tag
        fields = '__all__'


class ArticleCategorySerializer(serializers.ModelSerializer):
    """给分类详情的嵌套序列化器"""
    url = serializers.HyperlinkedIdentityField(view_name='article-detail')

    class Meta:
        model = Article
        fields = ['url', 'title']


class CategoryDetailSerializer(serializers.ModelSerializer):
    """分类详情"""
    articles = ArticleCategorySerializer(many=True, read_only=True)  # 该分类下的所有文章，故many=True

    class Meta:
        model = Category
        fields = ['id', 'title', 'create_datetime', 'articles']


class CategorySerializer(serializers.ModelSerializer):
    """分类序列化器"""
    url = serializers.HyperlinkedIdentityField(view_name='category-detail')

    class Meta:
        model = Category
        fields = '__all__'
        read_only_fields = ['create_datetime']


class ArticleBaseSerializer(serializers.HyperlinkedModelSerializer):
    """文章基础序列化器"""
    id = serializers.IntegerField(read_only=True)  # 前端路由动态地址，需要用到id
    author = UserDetailSerializer(read_only=True)

    category = CategorySerializer(read_only=True)
    # 外键category_id, 此处自动连接到该字段，用于创建/更新外键
    category_id = serializers.IntegerField(write_only=True, allow_null=True, required=False)

    # tags字段
    tags = serializers.SlugRelatedField(
        queryset=Tag.objects.all(),
        many=True,  # 由于标签字段是多对多，故many=True
        required=False,
        slug_field='text'  # text字段，仅显示该字段
    )

    # 图片
    avatar = AvatarSerializer(read_only=True)
    # 外键avatar_id, 此处自动连接到该字段，用于创建/更新外键
    avatar_id = serializers.IntegerField(write_only=True, allow_null=True, required=False)

    # category_id是否存在
    def validate_category_id(self, value):
        if not Category.objects.filter(id=value).exists() and value is not None:
            raise serializers.ValidationError("Category with id {} not exists.".format(value))
        return value  # 放行

    # avatar_id是否存在
    def validate_avatar_id(self, value):
        if not Avatar.objects.filter(id=value).exists() and value is not None:
            raise serializers.ValidationError("Avatar with id {} not exists.".format(value))
        return value  # 放行

    # 标签不存在时，创建它
    def to_internal_value(self, data):
        tags_data = data.get('tags')
        if isinstance(tags_data, list):
            for text in tags_data:
                if not Tag.objects.filter(text=text).exists():
                    Tag.objects.create(text=text)
        return super().to_internal_value(data)  # 调用父类方法


class ArticleSerializer(ArticleBaseSerializer):
    """文章序列化器"""
    class Meta:
        model = Article
        fields = '__all__'
        extra_kwargs = {'body': {'write_only': True}}


class ArticleDetailSerializer(ArticleBaseSerializer):
    """渲染后的文章详情序列化器"""
    id = serializers.IntegerField(read_only=True)
    comments = CommentSerializer(many=True, read_only=True)

    # 渲染后的正文， 通过get_body_html方法设定它的数据
    body_html = serializers.SerializerMethodField()
    # 渲染后的目录
    toc_html = serializers.SerializerMethodField()

    def get_body_html(self, obj):
        return obj.get_md()[0]

    def get_toc_html(self, obj):
        return obj.get_md()[1]

    class Meta:
        model = Article
        fields = '__all__'


#######################################################################################
# # HyperlinkedModelSerializer：在ModelSerializer的基础上，自动提供超链接url
# class ArticleSerializer(serializers.HyperlinkedModelSerializer):
#     """文章序列化器"""
#     author = UserDetailSerializer(read_only=True)
#     category = CategorySerializer(read_only=True)
#
#     # 外键category_id, 此处自动连接到该字段，用于创建/更新外键
#     category_id = serializers.IntegerField(write_only=True, allow_null=True, required=False)
#
#     # tags字段
#     tags = serializers.SlugRelatedField(
#         queryset=Tag.objects.all(),
#         many=True,  # 由于标签字段是多对多，故many=True
#         required=False,
#         slug_field='text'  # text字段，仅显示该字段
#     )
#
#     def validate_category_id(self, value):
#         if not Category.objects.filter(id=value).exists() and value is not None:
#             raise serializers.ValidationError("Category with id {} not exists.".format(value))
#         return value  # 放行
#
#     # 标签不存在时，创建它
#     def to_internal_value(self, data):
#         tags_data = data.get('tags')
#         if isinstance(tags_data, list):
#             for text in tags_data:
#                 if not Tag.objects.filter(text=text).exists():
#                     Tag.objects.create(text=text)
#         return super().to_internal_value(data)  # 调用父类方法
#
#     class Meta:
#         model = Article
#         fields = '__all__'






#######################################################################################
# class ArticleSerializer(serializers.ModelSerializer):
#     # 嵌套序列化器，仅读---也就是仅序列化，而不做校验（不用上传）
#     author = UserDetailSerializer(read_only=True)
#
#     # 超链接url-----此处为，文章详情的url，与urls.py文件中路由配置的name相关: name
#     # 由于是同一根目录下，故只是用name就可以了，否则，使用 “命名空间:name”如“article:detail”
#     url = serializers.HyperlinkedIdentityField(view_name='detail')
#
#     class Meta:
#         model = Article
#         fields = ['url', 'title', 'body', 'author']
#
#
# class ArticleDetailSerializer(serializers.ModelSerializer):
#     class Meta:
#         model = Article
#         fields = '__all__'
